package com.njtoyo.taxi.admin.rest.controller.data;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.njtoyo.taxi.admin.aop.PassToken;
import com.njtoyo.taxi.admin.aop.PermissionScope;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.enums.AppointmentCallState;
import com.njtoyo.taxi.admin.mapper.master.enums.RideCancellationTriggerBy;
import com.njtoyo.taxi.admin.mapper.master.enums.RideStateState;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.mapper.secondary.entity.data.DashboardCallDaily;
import com.njtoyo.taxi.admin.mapper.secondary.entity.data.DashboardCallDailyInfo;
import com.njtoyo.taxi.admin.mapper.secondary.mapper.data.DashboardCallDailyInfoMapper;
import com.njtoyo.taxi.admin.rest.presenter.business.ride.RideListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.chart.RankChartItemPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.IncomeChartPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.OrderChartPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.WholeDataPresenter;
import com.njtoyo.taxi.admin.rest.presenter.data.data_analysis.WorkingTaxiChartPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.data.data_analysis.*;
import com.njtoyo.taxi.admin.service.business.ride.RideCancellationService;
import com.njtoyo.taxi.admin.service.business.ride.RideService;
import com.njtoyo.taxi.admin.service.data.*;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.taxi.entity.common.RestResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.val;
import org.nutz.lang.random.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RequestMapping("/data/data_analysis")
@Api(value = "数据分析页接口", tags = "数据分析")
@RestController
public class DataAnalysisController {

    @Autowired
    private TodayAnalysisService dataAnalysisService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private IncomeService incomeService;

    @Autowired
    private RankListService rankListService;

    @Autowired
    private OverviewService overviewService;

    @Autowired
    private WorkingTaxiService workingTaxiService;

    @Autowired
    private WholeService wholeService;

    @Autowired
    private CallCustomerService callCustomerService;

    @Autowired
    private DriverServiceLogService driverServiceLogService;
    @Autowired
    private RealtimeCallMapper realtimeCallMapper;
    @Autowired
    private RideService rideService;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private DriverConfirmCallPersistedMapper driverConfirmCallPersistedMapper;
    @Autowired
    private DriverGrabRealtimePersistedMapper driverGrabRealtimePersistedMapper;
    @Autowired
    private DashboardCallDailyInfoMapper dashboardCallDailyInfoMapper;
    @Autowired
    private RideMapper rideMapper;
    @Autowired
    private TaxiMapper taxiMapper;
    @Autowired
    private RideCancellationMapper rideCancellationMapper;
    @Autowired
    private DriverKpiService driverKpiService;

    @GetMapping("today")
    @ApiOperation(value = "今日数据", notes = "权限：呼叫，订单：data_analysis_today_order;收入：data_analysis_today_income; 车俩：data_analysis_today_taxi;")
    @PermissionScope(names = {"data_analysis_today_order", "data_analysis_today_income", "data_analysis_today_taxi"})
    public RestResult today(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, @Valid TodayWrapper todayWrapper) {
        return dataAnalysisService.today(adminUser, todayWrapper);
    }


    @GetMapping("todayOpen")
    @PassToken
    @ApiOperation(value = "今日数据", notes = "权限：呼叫，订单：data_analysis_today_order;收入：data_analysis_today_income; 车俩：data_analysis_today_taxi;")
    public RestResult todayOpen(@RequestParam(required = false) String adCode) {
        return dataAnalysisService.todayOpen(adCode);
    }

    @GetMapping("/order_chart")
    @ApiOperation(value = "订单量趋势图", notes = "权限：data_analysis_order_chart;")
    @PermissionScope(names = {"data_analysis_order_chart"})
    public RestResult<List<OrderChartPresenter>> orderChart(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, ChartWrapper chartWrapper) {
        return orderService.orderChart(adminUser, chartWrapper);
    }

    @GetMapping("/income_chart")
    @ApiOperation(value = "收入趋势图", notes = "权限：data_analysis_income_chart;")
    @PermissionScope(names = {"data_analysis_income_chart"})
    public RestResult<List<IncomeChartPresenter>> incomeChart(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, ChartWrapper chartWrapper) {
        return incomeService.incomeChart(adminUser, chartWrapper);
    }

    @GetMapping("/working_taxi_chart")
    @ApiOperation(value = "出车率趋势图", notes = "权限：data_analysis_chart_working_taxi;")
    @PermissionScope(names = {"data_analysis_chart_working_taxi"})
    public RestResult<List<WorkingTaxiChartPresenter>> workingTaxi(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, ChartWrapper chartWrapper) {
        return workingTaxiService.workingTaxiChart(adminUser, chartWrapper);
    }

    @GetMapping("/rank_list")
    @ApiOperation(value = "排名统计", notes = "权限：data_analysis_rank_list;")
    @PermissionScope(names = {"data_analysis_rank_list"})
    public RestResult rankList(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, RankListWrapper rankListWrapper) {
        return rankListService.rankList(adminUser, rankListWrapper);
    }

    @GetMapping("/overview")
    @ApiOperation(value = "数据概览", notes = "权限：订单：data_analysis_overview_order, 收入：data_analysis_overview_income, 乘客：data_analysis_overview_customer, 车俩：data_analysis_overview_taxi, 司机：data_analysis_overview_driver")
    @PermissionScope(names = {"data_analysis_overview_order", "data_analysis_overview_income", "data_analysis_overview_customer", "data_analysis_overview_taxi", "data_analysis_overview_driver"})
    public RestResult overview(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, @Valid OverviewWrapper wrapper) {
        return overviewService.mainData(adminUser, wrapper);
    }

    @GetMapping("/rank_list/sub")
    @ApiOperation(value = "排名统计(展开)", notes = "权限：data_analysis_rank_list;")
    @PermissionScope(names = {"data_analysis_rank_list"})
    public RestResult rankSubList(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, RankListWrapper rankListWrapper) {
        return rankListService.rankSubList(adminUser, rankListWrapper);
    }

    @GetMapping("/whole")
    @ApiOperation(value = "数据总览", notes = "权限：订单：data_analyse_all_order, 乘客：data_analyse_all_customer, 车俩：data_analyse_all_taxi, 司机：data_analyse_all_driver")
    @PermissionScope(names = {"data_analyse_all_order", "data_analyse_all_customer", "data_analyse_all_driver", "data_analyse_all_taxi"})
    public RestResult<WholeDataPresenter> all(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, WholeDataWrapper wrapper) {
        return wholeService.mainData(adminUser, wrapper);
    }

    @GetMapping("/call_customer_chart")
    @ApiOperation(value = "呼叫乘客趋势图", notes = "权限：data_analysis_overview_customer;")
    @PermissionScope(names = {"data_analysis_overview_customer"})
    public RestResult<List<RankChartItemPresenter>> callCustomerChart(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, ChartWrapper chartWrapper) {
        return callCustomerService.chart(adminUser, chartWrapper);
    }

    @GetMapping("/working_taxi_count_chart")
    @ApiOperation(value = "出车数量趋势图", notes = "权限：data_analysis_overview_taxi;")
    @PermissionScope(names = {"data_analysis_overview_taxi"})
    public RestResult<List<RankChartItemPresenter>> workingTaxiChart(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, ChartWrapper chartWrapper) {
        return driverServiceLogService.workingTaxiChart(adminUser, chartWrapper);
    }

    @GetMapping("/working_driver_count_chart")
    @ApiOperation(value = "出车司机数量趋势图", notes = "权限：data_analysis_overview_driver;")
    @PermissionScope(names = {"data_analysis_overview_driver"})
    public RestResult<List<RankChartItemPresenter>> workingDriverChart(@ApiIgnore @ModelAttribute("admin") AdminUser adminUser, ChartWrapper chartWrapper) {
        return driverServiceLogService.workingDriverChart(adminUser, chartWrapper);
    }

    @GetMapping("/driver")
    public RestResult<?> driverData(@ModelAttribute("admin") AdminUser adminUser, DriverDataWrapper wrapper) {
        return driverServiceLogService.driverData(adminUser, wrapper);
    }


    @GetMapping("/driver/export")
    public void driverDataExport(@ModelAttribute("admin") AdminUser adminUser, DriverDataWrapper wrapper, HttpServletResponse response) {
        driverKpiService.driverDataExport(adminUser, wrapper, response);
    }


    /**
     * 参与行程订单抢单的司机
     *
     * @return
     */
    @GetMapping("/rideJoinDriver")
    @PassToken
    public RestResult<?> rideJoinDriver(@RequestParam String callId) {
        Map<String, Object> result = dataAnalysisService.rideJoinDriver(callId);
        return RestResult.success(result);
    }


    //todo 这个接口是不是没用了？ 2025-05-06 qp
    @GetMapping("/getTodayRide")
    @PassToken
    public RestResult<?> getTodayRide(@RequestParam(value = "current", required = false, defaultValue = "1") Integer current,
                                      @RequestParam(value = "size", required = false, defaultValue = "10") Integer size) {
        Page page = new Page(current, size);
                Page<RealtimeCall> pages = realtimeCallMapper.selectPage(page, Wrappers.<RealtimeCall>
                                lambdaQuery().orderByDesc(RealtimeCall::getId).between(RealtimeCall::getAreaId, 174, 177)
                        .between(RealtimeCall::getCreatedAt, DateUtil.beginOfDay(DateUtil.date()), DateUtil.endOfDay(DateUtil.date()))
        );
        IPage<Map<String, Object>> res = new Page<>();
        List<Map<String, Object>> list = new ArrayList<>();
        if (ObjectUtil.isNotEmpty(pages.getRecords())) {
            List<Long> callIds = pages.getRecords().stream().map(RealtimeCall::getId).collect(Collectors.toList());
            List<Map<String, Object>> sendMaps = driverConfirmCallPersistedMapper.selectSendNumByCallIds(callIds,0);
            Map<Long, Integer> sendMap = sendMaps.stream().collect(Collectors.toMap(m -> MapUtil.getLong(m, "callId"), m -> MapUtil.getInt(m, "driverNum")));
            List<Map<String, Object>> grabMaps = driverGrabRealtimePersistedMapper.selectGrabDriverNumByCallIds(callIds);
            Map<Long, Integer> grabMap = grabMaps.stream().collect(Collectors.toMap(m -> MapUtil.getLong(m, "callId"), m -> MapUtil.getInt(m, "grabNum")));
            List<Ride> rides = rideService.getListByCallIds(callIds);
            Map<Long, Ride> rideMap = rides.stream().collect(Collectors.toMap(Ride::getRefId, Function.identity()));
            for (Object call : page.getRecords()) {
                RealtimeCall realtimeCall = (RealtimeCall) call;
                Map<String, Object> realtimeCallMap = BeanUtil.beanToMap(realtimeCall);
                Ride r = rideMap.get(realtimeCall.getId());
                if (ObjectUtil.isNotNull(r)) {
                    realtimeCallMap.put("state", r.getState().name());
                    realtimeCallMap.put("rideId", r.getId());
                    realtimeCallMap.put("receiveDate", ObjectUtil.isNotNull(r.getCreatedAt()) ? r.getCreatedAt() : "-");
                    RideCancellation rideCancellation = rideCancellationMapper.selectOne(Wrappers.<RideCancellation>lambdaQuery()
                            .eq(RideCancellation::getRideId, r.getId()));
                    if (ObjectUtil.isNotNull(rideCancellation)) {
                        realtimeCallMap.put("cancellationDate", ObjectUtil.isNotNull(rideCancellation.getCreatedAt()) ? rideCancellation.getCreatedAt() : "-");
                        if (rideCancellation.getTriggerBy() == RideCancellationTriggerBy.driver) {
                            realtimeCallMap.put("state", "cancel_driver");
                        } else if (rideCancellation.getTriggerBy() == RideCancellationTriggerBy.customer) {
                            realtimeCallMap.put("state", "cancel_customer");
                        } else if (rideCancellation.getTriggerBy() == RideCancellationTriggerBy.admin) {
                            realtimeCallMap.put("state", "cancel_admin");
                        }
                    }
                } else if (realtimeCall.getState() == AppointmentCallState.cancelled) {
                    realtimeCallMap.put("cancellationDate", ObjectUtil.isNotNull(realtimeCall.getUpdatedAt()) ? realtimeCall.getUpdatedAt() : "-");
                    if (realtimeCall.getState()  == AppointmentCallState.cancelled) {
                        realtimeCallMap.put("state", "cancel_customer");
                    } else if (realtimeCall.getState()  == AppointmentCallState.covered) {
                        realtimeCallMap.put("state", "cancel_system");
                    }
                }
                //乘客信息
                User user = userMapper.selectById(realtimeCall.getCustomerId());
                if (ObjectUtil.isNotNull(user)) {
                    realtimeCallMap.put("userName", user.getName());
                }
                //发送司机数
                realtimeCallMap.put("sendNum", ObjectUtil.isNull(sendMap.get(realtimeCall.getId())) ? 0 : sendMap.get(realtimeCall.getId()));
                //抢单司机数
                realtimeCallMap.put("grabCount", ObjectUtil.isNull(grabMap.get(realtimeCall.getId())) ? 0 : grabMap.get(realtimeCall.getId()));
                list.add(realtimeCallMap);
            }
        }
        res.setRecords(list);
        res.setCurrent(pages.getCurrent());
        res.setPages(pages.getPages());
        res.setSize(pages.getSize());
        res.setTotal(pages.getTotal());
        return RestResult.success(res);
    }


    @GetMapping("/get30DayRide")
    @PassToken
    public RestResult<?> get30DayRide() {
        List<DashboardCallDailyInfo> list = dashboardCallDailyInfoMapper.selectList(Wrappers.<DashboardCallDailyInfo>lambdaQuery()
                .between(DashboardCallDailyInfo::getCreateDate, DateUtil.formatDate(DateUtil.offsetDay(DateUtil.date(), -30)), DateUtil.formatDate(DateUtil.date()))
                .orderByDesc(DashboardCallDailyInfo::getCreateDate));
        return RestResult.success(list);
    }


    @GetMapping("/getCountToDayRide")
    @PassToken
    public RestResult<?> getCountToDayRide() {
        List<Map<String, Object>> realtimeCallListMap = realtimeCallMapper.selectMaps(Wrappers.<RealtimeCall>lambdaQuery()
                .between(RealtimeCall::getCreatedAt, DateUtil.beginOfDay(DateUtil.date()), DateUtil.endOfDay(DateUtil.date()))
                .orderByDesc(RealtimeCall::getId));
        List<Long> callIds = realtimeCallListMap.stream().map(real -> MapUtil.getLong(real, "id")).collect(Collectors.toList());
        List<Ride> rides = rideMapper.selectList(Wrappers.<Ride>lambdaQuery()
                .in(Ride::getRefId, callIds)
                .in(Ride::getState, Arrays.asList(RideStateState.ended, RideStateState.completed, RideStateState.marked)));
        int sendNum = driverConfirmCallPersistedMapper.selectCountSendNum(callIds,0);
        int joinCount = driverGrabRealtimePersistedMapper.selectCountJoinDriver(callIds);
        Integer outCarNum = taxiMapper.selectCount(Wrappers.<Taxi>lambdaQuery().in(Taxi::getIsAvailable, 1));
        Map<String, Integer> result = new HashMap<>();
        result.put("callNum", CollUtil.isNotEmpty(callIds) ? callIds.size() : 0);
        result.put("completeNum", CollUtil.isNotEmpty(rides) ? rides.size() : 0);
        result.put("sendNum", sendNum);
        result.put("joinCount", joinCount);
        result.put("outCarNum", ObjectUtil.isNull(outCarNum) ? 0 : outCarNum);
        return RestResult.success(result);
    }


    @GetMapping("/getGrapNum")
    @PassToken
    public RestResult<?> getGrapNum() {
        return dataAnalysisService.getGrapNum();
    }


    @GetMapping("/getFinishOrderByHour")
    @PassToken
    public RestResult<?> getFinishOrderByHour() {
        return dataAnalysisService.getDoneOrderByHour();
    }


    @GetMapping("/getFinishOrderByDay")
    @PassToken
    public RestResult<?> getFinishOrderByDay() {
        return dataAnalysisService.getFinishOrderByDay();
    }


    @GetMapping("/getCancelAnalyse")
    @PassToken
    public RestResult<?> getCancelAnalyse() {
        return dataAnalysisService.getCancelAnalyse();
    }


}
